import * as THREE from 'three'
import * as geo from 'd3-geo'
import {CSS2DRenderer, CSS2DObject} from 'three/examples/jsm/renderers/CSS2DRenderer';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
import axios from "axios";
import world from '@/utils/countries.geo.json'

THREE.Cache.enabled = true;
const FPS = 18;
// date()
const clock = new THREE.Clock();

class threeUtils {
  scene = null;
  renderer = null
  camera = null;
  ambientLight = null;
  container = null;
  control = null;
  WIDTH = 0;
  HEIGHT = 0;
  loader = null
  mapUrl = '';
  worldUrl = "";
  scaleVal = 150;
  renderT = 1 / FPS
  group = new THREE.Group()
  textureLoader = new THREE.TextureLoader()
  points = new Array()
  worldPoints = new Array()
  timeS = 0
  labelRenderer = null
  animation = null
  rotatingApertureMesh = null
  rotatingPointMesh = null
  /**设置范围*/
  particleArr = []
  WaveMeshArr = []

  constructor() {
  }

  /**初始化*/
  async init(container, mapUrl,url) {
    //   新建场景
    this.WIDTH = container.offsetWidth;
    this.HEIGHT = container.offsetHeight;
    this.container = container;
    this.mapUrl = mapUrl;
    this.initRender()
    this.scene = new THREE.Scene()
    this.initLight()
    this.initCamera()
    this.initController()
    // 全景图
    this.points = await this.initGetGeoJson(mapUrl)
    console.log(world,url==='world')
    this.initMap(url==='world'?world:this.points.data,url)
    // this.worldPoints = await this.initGetGeoJson(worldUrl)
    // this.initWorld(this.worldPoints.data)
    this.initPoints()
    // this.SphereGeometry()
    this.initFloor()
    // 设置范围
    this.initParticle()
    //  执行渲染
    this.render()
  }

  /**render*/
  initRender() {
    //   设置渲染器
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });
    this.renderer.setPixelRatio(window.devicePixelRatio)
    this.renderer.setSize(this.WIDTH, this.HEIGHT);
    this.container.appendChild(this.renderer.domElement);

    this.labelRenderer = new CSS2DRenderer()
    this.labelRenderer.setSize(this.WIDTH, this.HEIGHT)
    this.labelRenderer.domElement.style.position = 'absolute'
    this.labelRenderer.domElement.style.top = '0px'
    this.labelRenderer.domElement.style.pointerEvents = 'none'
    this.container.appendChild(this.labelRenderer.domElement)
  }

  /**初始化相机*/
  initCamera() {
    // 长度和宽度比 默认采用浏览器 返回以像素为单位的窗口的内部宽度和高度
    this.camera = new THREE.PerspectiveCamera(45, this.WIDTH / this.HEIGHT, 0.1, 1050);
    // 确定相机位置 并将相机指向场景中心
    this.camera.position.x = 3.4
    this.camera.position.y = 118
    this.camera.position.z = 92
    this.camera.lookAt(this.scene.position)
  }

  /**设置环境光*/
  initLight() {
    // this.scene.add(new THREE.AmbientLight(0x7af4ff, 1.2))
    this.scene.add(new THREE.AmbientLight(0xbbbbbb, 1.2))
    const directionalLight1 = new THREE.DirectionalLight(0x666666, 1) // 037af1
    // const directionalLight1 = new THREE.DirectionalLight(0x7af4ff, 1) // 037af1
    directionalLight1.position.set(-100, 10, -100)
    const directionalLight2 = new THREE.DirectionalLight(0x7af4ff, 1)
    directionalLight2.position.set(100, 10, 100)
    this.scene.add(directionalLight1)
    this.scene.add(directionalLight2)
  }

  /**背景图*/
  SphereGeometry() {
    const texture = this.textureLoader.load(
      '/image/bathymetry_bw_composite_4k.jpg'
    )
    const sphereGeometry = new THREE.SphereGeometry(1, 50, 50);
    sphereGeometry.scale(1, 1, -1)
    const sphereMaterial = new THREE.MeshBasicMaterial({map: texture});
    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    this.scene.add(sphere)
  }

  /**自适应*/
  onWindowResize(data,world) {
    this.WIDTH = this.container.offsetWidth
    this.HEIGHT = this.container.offsetHeight
    this.camera.aspect = this.container.offsetWidth / this.container.offsetHeight
    this.camera.updateProjectionMatrix()
    this.renderer.setSize(this.WIDTH, this.HEIGHT)
    // console.log(data,'data',world)
    setTimeout(()=>this.pointHandler(data,world),500)
  }
  initGetGeoJson(map) {
    this.loader = new THREE.FileLoader()
    const data = axios.get(map);
    return data
  }

  initWorld(data) {
// 墨卡托投影转换
    const projection = geo
      .geoMercator()
      .center([19.5, 47.26])
      .scale(this.scaleVal)
      .translate([0, 0])

    data.features.forEach((elem) => {
      const province = new THREE.Object3D();
      const {coordinates} = elem.geometry;
      coordinates.forEach(multiPolygon => {
        multiPolygon.forEach((polygon) => {
          const shape = new THREE.Shape();
          const lineMaterial2 = new THREE.LineBasicMaterial({
            color: 'white',
            transparent: true,
            opacity: .5
          })
          const lineGeometry2 = new THREE.BufferGeometry({
            color: "white",
            opacity: 0.8
          });
          const pointsArray = new Array()
          for (let i = 0; i < polygon.length; i++) {
            let [x, y] = projection(polygon[i]);
            if (!isNaN(x)) {
              if (i === 0 || isNaN(x)) {
                shape.moveTo(x, -y);
              }
              shape.lineTo(x, -y);
              pointsArray.push(new THREE.Vector3(x, -y, 5.01))
            }
          }

          lineGeometry2.setFromPoints(pointsArray)
          const extrudeSettings = {
            depth: .1,
            bevelEnabled: false,
          };
          const line = new THREE.Line(lineGeometry2, lineMaterial2)
          const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
          const material = new THREE.MeshBasicMaterial({color: "#162633", transparent: false})
          const mesh = new THREE.Mesh(geometry, material)
          //
          mesh.rotateX(-Math.PI / 2)
          line.rotateX(-Math.PI / 2)
          line.position.y = -5;
          province.add(mesh)
          province.add(line)
        })
      })
      //光源
      this.scene.add(province);
    })
  }

  /**加载地图*/
  initMap(data,url) {
    // 墨卡托投影转换

    const projection = geo.geoMercator()
      .center(url==="world"?[19.5, 47.26]:[102.44662948242187, 30.927128325051036])
      .scale(this.scaleVal)
      .translate([0, 0])
    data.features.forEach((elem) => {
      // 定一个省份3D对象
      // Object3d是three.js 所有的基类, 提供了一系列的属性和方法来对三维空间中的物体进行操纵。可以通过.add( object )方法来将对象进行组合，该方法将对象添加为子对象
      const province = new THREE.Object3D();
      // 每个的 坐标 数组
      const {coordinates} = elem.geometry;
      // 循环坐标数组
      coordinates.forEach(multiPolygon => {
        if(typeof multiPolygon[0][0]=="number"){
          // 定义二维形状的平面
          const shape = new THREE.Shape();
          const lineMaterial2 = new THREE.LineBasicMaterial({
            color: '#169C89',
            transparent: true,
            opacity: 1.0
          })
          // 自定义信息
          // lineGeometry 对应的是轮廓的边线
          const lineGeometry2 = new THREE.BufferGeometry({
            color: "#169C89",
            opacity: 0.8
          });

          const pointsArray = new Array()

          for (let i = 0; i < multiPolygon.length; i++) {
            let [x, y] = projection(multiPolygon[i]);
            if (!isNaN(x)) {
              if (i === 0) {
                shape.moveTo(x, -y);
              }
              shape.lineTo(x, -y);
              pointsArray.push(new THREE.Vector3(x, -y, 5.01))
            }
          }


          lineGeometry2.setFromPoints(pointsArray)

          const extrudeSettings = {
            // 挤出的形状的深度，默认值为1。
            depth: .9,
            // 对挤出的形状应用是否斜角，默认值为true。
            bevelEnabled: false,
            // 设置原始形状上斜角的厚度。默认值为0.2。
            // bevelThickness:0.4,
            //斜角与原始形状轮廓之间的延伸距离。
            // bevelSize:1,
            // 斜角的分段层数。
            // bevelSegments:2
          };
          const extrudeSettings1 = {
            // 挤出的形状的深度，默认值为1。
            depth: 4,
            // 对挤出的形状应用是否斜角，默认值为true。
            bevelEnabled: false,
            // 设置原始形状上斜角的厚度。默认值为0.2。
            bevelThickness: 0.4,
            //斜角与原始形状轮廓之间的延伸距离。
            bevelSize: 1,
            // 斜角的分段层数。
            bevelSegments: 2
          };
          const line2 = new THREE.Line(lineGeometry2, lineMaterial2)
          // 底线
          // const line1 = new THREE.Line(lineGeometry1,lineMaterial1)
          // line1.computeLineDistances();
          //
          const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
          const material = new THREE.MeshBasicMaterial({color: "#00FFFF", transparent: false, fog: true})
          // const material = new THREE.MeshBasicMaterial({color:"white",transparent:false,opacity:0.38,})
          const mesh = new THREE.Mesh(geometry, material)

          const geometry1 = new THREE.ExtrudeGeometry(shape, extrudeSettings1)
          const material1 = new THREE.MeshBasicMaterial({color: "#1D5CBB", transparent: true, opacity: 0.9})
          const mesh1 = new THREE.Mesh(geometry1, material1)
          //
          mesh.rotateX(-Math.PI / 2)
          mesh1.rotateX(-Math.PI / 2)
          mesh1.position.y = .9;
          line2.rotateX(-Math.PI / 2)
          province.add(mesh)
          province.add(mesh1)
          province.add(line2)
          // // 给mesh开启阴影
          mesh.castShadow = true
          mesh.receiveShadow = true
        }else {
          multiPolygon.forEach((polygon) => {
            // 定义二维形状的平面
            const shape = new THREE.Shape();
            const lineMaterial2 = new THREE.LineBasicMaterial({
              color: '#169C89',
              transparent: true,
              opacity: 1.0
            })
            // 自定义信息
            // lineGeometry 对应的是轮廓的边线
            const lineGeometry2 = new THREE.BufferGeometry({
              color: "#169C89",
              opacity: 0.8
            });

            const pointsArray = new Array()

            if (typeof polygon[0] == "number") {
              // console.log(polygon)
              // let [x, y] = projection(polygon);
              // if (!isNaN(x)) {
              //   shape.lineTo(x, -y);
              //   pointsArray.push(new THREE.Vector3(x, -y, 5.01))
              // }
            } else {
              for (let i = 0; i < polygon.length; i++) {
                let [x, y] = projection(polygon[i]);
                if (!isNaN(x)) {
                  if (i === 0) {
                    shape.moveTo(x, -y);
                  }
                  shape.lineTo(x, -y);
                  pointsArray.push(new THREE.Vector3(x, -y, 5.01))
                }
              }
            }

            lineGeometry2.setFromPoints(pointsArray)

            const extrudeSettings = {
              // 挤出的形状的深度，默认值为1。
              depth: .9,
              // 对挤出的形状应用是否斜角，默认值为true。
              bevelEnabled: false,
              // 设置原始形状上斜角的厚度。默认值为0.2。
              // bevelThickness:0.4,
              //斜角与原始形状轮廓之间的延伸距离。
              // bevelSize:1,
              // 斜角的分段层数。
              // bevelSegments:2
            };
            const extrudeSettings1 = {
              // 挤出的形状的深度，默认值为1。
              depth: 4,
              // 对挤出的形状应用是否斜角，默认值为true。
              bevelEnabled: false,
              // 设置原始形状上斜角的厚度。默认值为0.2。
              bevelThickness: 0.4,
              //斜角与原始形状轮廓之间的延伸距离。
              bevelSize: 1,
              // 斜角的分段层数。
              bevelSegments: 2
            };
            const line2 = new THREE.Line(lineGeometry2, lineMaterial2)
            // 底线
            // const line1 = new THREE.Line(lineGeometry1,lineMaterial1)
            // line1.computeLineDistances();
            //
            const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
            const material = new THREE.MeshBasicMaterial({color: "#00FFFF", transparent: false, fog: true})
            // const material = new THREE.MeshBasicMaterial({color:"white",transparent:false,opacity:0.38,})
            const mesh = new THREE.Mesh(geometry, material)

            const geometry1 = new THREE.ExtrudeGeometry(shape, extrudeSettings1)
            const material1 = new THREE.MeshBasicMaterial({color: "#1D5CBB", transparent: true, opacity: 0.9})
            const mesh1 = new THREE.Mesh(geometry1, material1)
            //
            mesh.rotateX(-Math.PI / 2)
            mesh1.rotateX(-Math.PI / 2)
            mesh1.position.y = .9;
            line2.rotateX(-Math.PI / 2)
            province.add(mesh)
            province.add(mesh1)
            province.add(line2)
            // // 给mesh开启阴影
            mesh.castShadow = true
            mesh.receiveShadow = true
          })
        }
      })
      //光源
      this.scene.add(province);
    })
  }

  /**初始化控制器*/
  initController() {
    this.control = new OrbitControls(this.camera, this.renderer.domElement)
    this.control.enableDamping = true
    this.control.enableZoom = true
    this.control.autoRotate = false
    this.control.minDistance = 1
    this.control.maxDistance = 400
    this.control.maxPolarAngle = (Math.PI / 180) * 75
    this.control.enablePan = true;
    this.control.update()
  }

  /**点*/
  initPoints() {
    const texture = this.textureLoader.load(
      '/jsonimg/gradient.png'
    )
    const positions = []
    const colors = []
    const geometry = new THREE.BufferGeometry()
    const vertexCommon = new THREE.Vector3()
    for (let i = 0; i < 100; i++) {
      const vertex = vertexCommon.clone()
      vertex.x = Math.random() * 2 - 1
      vertex.y = Math.random() * 2 - 1
      vertex.z = Math.random() * 2 - 1
      positions.push(vertex.x, vertex.y, vertex.z)
      // console.log(positions)
      const color = new THREE.Color()
      color.setHSL(
        Math.random() * 0.2 + 0.5,
        0.55,
        Math.random() * 0.25 + 0.55
      )
      colors.push(color.r, color.g, color.b)
    }
    geometry.setAttribute(
      'position',
      new THREE.Float32BufferAttribute(positions, 3)
    )
    geometry.setAttribute(
      'color',
      new THREE.Float32BufferAttribute(colors, 3)
    )
    const starsMaterial = new THREE.PointsMaterial({
      map: texture,
      size: 1,
      transparent: true,
      opacity: 1,
      vertexColors: true, // true：且该几何体的colors属性有值，则该粒子会舍弃第一个属性--color，而应用该几何体的colors属性的颜色
      blending: THREE.AdditiveBlending,
      sizeAttenuation: true
    })
    this.stars = new THREE.Points(geometry, starsMaterial)
    this.stars.scale.set(300, 300, 300)
    this.scene.add(this.stars)
  }

  initFloor() {
    //更新为较新的api
    const geometry = new THREE.PlaneGeometry(400, 400)
    const texture = this.textureLoader.load('/jsonimg/地板背景.png')
    const material = new THREE.MeshPhongMaterial({
      color: 'black',
      map: texture,
      transparent: true,
      opacity: 1,
      depthTest: true,
      depthWrite: false
    })
    const plane = new THREE.Mesh(geometry, material)
    plane.rotateX(-Math.PI / 2)
    this.scene.add(plane)

    const rotatingApertureTexture = this.textureLoader.load(
      '/jsonimg/rotatingAperture.png'
    )
    const rotatingApertureerial = new THREE.MeshBasicMaterial({
      map: rotatingApertureTexture,
      transparent: true,
      opacity: 1,
      depthTest: true,
      depthWrite: false
    })
    const rotatingApertureGeometry = new THREE.PlaneGeometry(100, 100)
    this.rotatingApertureMesh = new THREE.Mesh(
      rotatingApertureGeometry,
      rotatingApertureerial
    )
    this.rotatingApertureMesh.rotateX(-Math.PI / 2)
    this.rotatingApertureMesh.position.y = 0.02
    this.rotatingApertureMesh.scale.set(1.2, 1.2, 1.2)
    this.scene.add(this.rotatingApertureMesh)
    const rotatingPointTexture = this.textureLoader.load(
      '/jsonimg/rotating-point2.png'
    )
    const material2 = new THREE.MeshBasicMaterial({
      map: rotatingPointTexture,
      transparent: true,
      opacity: 1,
      depthTest: true,
      depthWrite: false
    })
    this.rotatingPointMesh = new THREE.Mesh(rotatingApertureGeometry, material2)
    this.rotatingPointMesh.rotateX(-Math.PI / 2)
    this.rotatingPointMesh.position.y = 0.04
    this.rotatingPointMesh.scale.set(1, 1, 1)
    this.scene.add(this.rotatingPointMesh)
    const circlePoint = this.textureLoader.load(
      '/jsonimg/circle-point.png'
    )
    const material3 = new THREE.MeshPhongMaterial({
      color: 0x00ffff,
      map: circlePoint,
      transparent: true,
      opacity: 1,
      depthWrite: false
      // depthTest: false,
    })
    const plane3 = new THREE.PlaneGeometry(120, 120)
    const mesh3 = new THREE.Mesh(plane3, material3)
    mesh3.rotateX(-Math.PI / 2)
    mesh3.position.y = 0.06
    this.scene.add(mesh3)
  }

  /**设置范围 用于粒子上升*/
  initParticle() {
    // 设置范围
    const minX = -60
    const maxX = 60
    const minY = -10
    const maxY = 30
    const minZ = -60
    const maxZ = 60

    for (let i = 0; i < 15; i++) {
      const particle = this.createSequenceFrame({
        image: '/jsonimg/上升粒子1.png',
        width: 180,
        height: 189,
        frame: 9,
        column: 9,
        row: 1,
        speed: 0.5
      })
      const particleScale = this.random(5, 10) / 100
      particle.scale.set(particleScale, particleScale, particleScale)
      const x = this.random(minX, maxX)
      const y = this.random(minY, maxY)
      const z = this.random(minZ, maxZ)
      particle.position.set(x, y, z)
      this.particleArr.push(particle)
    }
    this.scene.add(...this.particleArr)
    return this.particleArr
  }

  createSequenceFrame(opt) {
    // 默认参数
    const options = this.deepMerge({
        image: '',
        width: 200, // 显示的宽度
        height: 200, // 显示的高度
        frame: 60, // 总共的帧数
        column: 10, // 序列图的列
        row: 6, // 序列图的行
        speed: 0.5 // 速度
      },
      opt
    )
    const geometry = new THREE.PlaneGeometry(
      options.width,
      options.height
    ) // 矩形平面
    const texture = this.textureLoader.load(options.image) // 加载图片
    texture.repeat.set(1 / options.column, 1 / options.row) // 从图像上截图第一帧
    const material = new THREE.MeshBasicMaterial({
      map: texture,
      transparent: true,
      opacity: 1,
      side: THREE.DoubleSide,
      depthWrite: false // 是否对深度缓冲区有任何的影响
    })
    const mesh = new THREE.Mesh(geometry, material)

    let r = 0 // 当前行
    let c = 0 // 当前列
    let t = 0 // 时间
    mesh.updateSequenceFrame = () => {
      t += options.speed
      if (t > options.frame) t = 0
      c = options.column - Math.floor(t % options.column) - 1
      r = Math.floor((t / options.column) % options.row)
      texture.offset.x = c / options.column // 动态更新纹理偏移 播放关键帧动画
      texture.offset.y = r / options.row // 动态更新纹理偏移 播放关键帧动画
    }

    return mesh
  }

  deepMerge(target, source) {
    target = this.deepClone(target)
    for (const key in source) {
      if (key in target) {
        // 对象的处理
        if (this.isObject(source[key])) {
          if (!this.isObject(target[key])) {
            target[key] = source[key]
          } else {
            target[key] = this.deepMerge(target[key], source[key])
          }
        } else {
          target[key] = source[key]
        }
      } else {
        target[key] = source[key]
      }
    }
    return target
  }

  deepClone(target, map = new Map()) {
    // target 不能为空，并且是一个对象
    if (target != null && this.isObject(target)) {
      // 在克隆数据前，进行判断是否克隆过,已克隆就返回克隆的值
      let cache = map.get(target)
      if (cache) {
        return cache
      }
      // 判断是否为数组
      const isArray = Array.isArray(target)
      const result = isArray ? [] : {}
      // 将新结果存入缓存中
      cache = map.set(target, result)
      // 如果是数组
      if (isArray) {
        // 循环数组，
        target.forEach((item, index) => {
          // 如果item是对象，再次递归
          result[index] = this.deepClone(item, cache)
        })
      } else {
        // 如果是对象
        Object.keys(target).forEach((key) => {
          if (this.isObject(result[key])) {
            result[key] = this.deepClone(target[key], cache)
          } else {
            result[key] = target[key]
          }
        })
      }
      return result
    } else {
      return target
    }
  }

  isObject(value) {
    return this.isType('Object', value)
  }

  isType(type, value) {
    return Object.prototype.toString.call(value) === `[object ${type}]`
  }

  random(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
  }

  /**end*/
  /**添加坐标点*/
  pointHandler(list,url) {
    const projection = geo
      .geoMercator()
      .center(url?[19.15,47]:[102.44662948242187, 30.927128325051036])
      .scale(this.scaleVal)
      .translate([0, 0])
    console.log(list,'data')
    // TODO
    list.forEach((el) => {
      this.initLightPoint(el, projection)
    })
  }

  initLightPoint(properties, projection) {
    const heightScaleFactor = 10 + this.random(1, 5) / 5
    const lightCenter = [properties.lng, properties.lat]
    const [x, y] = projection(lightCenter)
    const light = this.createLightPillar(x, y, heightScaleFactor)
    light.position.z -= 3
    this.scene.add(light)
    this.createTextPoint(x, y, properties.name, properties.capacity)
  }

  createTextPoint(x, z, areaName, val) {
    const tag = document.createElement('div')
    tag.innerHTML = `${areaName}`
    tag.style.pointerEvents = 'none'
    tag.style.position = 'absolute'
    tag.style.fontSize = '6px'
    tag.style.border = '1px solid #37dbff'
    // tag.style.background = '#0e2e6c'
    tag.style.background = `#0e2e6c`
    tag.style.backgroundSize = '100% 100%'
    const label = new CSS2DObject(tag)
    label.element.innerHTML = `<div style="transform: scale(0.6);font-size: 8px">${areaName}<br />月产能:${val}</div>`
    label.element.style.visibility = 'visible'
    label.element.style.fontSize = '6px'
    const y = areaName === '中国江苏溧阳厂区' ? 30 : 15
    label.position.set(x+12, y, z)
    label.position.z -= 3
    this.scene.add(label)
  }

  /**创建光锥*/
  createLightPillar(x, z, heightScaleFactor = 50) {
    const group = new THREE.Group()
    const height = heightScaleFactor
    // 柱体的geo,6.19=柱体图片高度/宽度的倍数
    const geometry = new THREE.PlaneGeometry(height / 8, height)
    geometry.translate(0, height / 2, 0)
    const m = new THREE.CylinderGeometry(2, 0, 8, 5, 5, false)
    m.translate(0, height / 2, 0)
    const material = new THREE.MeshPhongMaterial({
      color: '#F4A91B',
      transparent: false,
      wireframeLinecap: true,
      specular: "#FFFF18"
    });
    const light01 = new THREE.Mesh(m, material)
    this.scene.add(light01)
    const bottomMesh = this.createPointMesh(1.5)
    const lightHalo = this.createLightHalo(3)
    this.WaveMeshArr.push(lightHalo)
    group.add(bottomMesh, lightHalo, light01)
    group.position.set(x, 4.01, z)
    return group
  }

  createPointMesh(size) {
    const geometry = new THREE.PlaneGeometry(1, 1)
    const material = new THREE.MeshBasicMaterial({
      map: this.textureLoader.load('/jsonimg/标注.png'),
      color: '#FFFF18',
      side: THREE.DoubleSide,
      transparent: true,
      depthWrite: false // 禁止写入深度缓冲区数据
    })
    const mesh = new THREE.Mesh(geometry, material)
    mesh.position.y = 1
    mesh.renderOrder = 2
    mesh.rotation.x = Math.PI / 2
    mesh.name = 'createPointMesh'
    // 缩放
    const scale = 1 * size
    mesh.scale.set(scale, scale, scale)
    return mesh
  }

  createLightHalo(size) {
    const geometry = new THREE.PlaneGeometry(1, 1)
    const material = new THREE.MeshBasicMaterial({
      map: this.textureLoader.load('/jsonimg/标注光圈.png'),
      color: "#FFFF18",
      side: THREE.DoubleSide,
      opacity: 0,
      transparent: true,
      depthWrite: false // 禁止写入深度缓冲区数据
    })
    const mesh = new THREE.Mesh(geometry, material)
    mesh.position.y = 1
    mesh.renderOrder = 2
    mesh.name = 'createLightHalo'
    mesh.rotation.x = Math.PI / 2
    // 缩放
    const scale = 1.5 * size
    mesh.size = scale // 自顶一个属性，表示mesh静态大小
    mesh.scale.set(scale, scale, scale)
    return mesh
  }

  /**
   *执行 + 动画
   * */
  render() {
    let T = clock.getDelta()
    this.timeS += T
    this.animation = requestAnimationFrame(this.render.bind(this))
    /** 动画效果*/
    if (this.timeS > this.renderT) {
      if (this.rotatingApertureMesh) {
        this.rotatingApertureMesh.rotation.z += 0.0005
      }
      if (this.rotatingPointMesh) {
        this.rotatingPointMesh.rotation.z -= 0.0005
      }
    }
    if (this.particleArr.length) {
      for (let i = 0; i < this.particleArr.length; i++) {
        this.particleArr[i].updateSequenceFrame()
        this.particleArr[i].position.y += 1
        if (this.particleArr[i].position.y >= 50) {
          this.particleArr[i].position.y = -10
        }
      }
    }
    if (this.WaveMeshArr.length) {
      this.WaveMeshArr.forEach(function (mesh) {
        mesh._s += 0.007
        mesh.scale.set(
          mesh.size * mesh._s,
          mesh.size * mesh._s,
          mesh.size * mesh._s
        )
        if (mesh._s <= 1.5) {
          // mesh._s=1，透明度=0 mesh._s=1.5，透明度=1
          mesh.material.opacity = (mesh._s - 1) * 2
        } else if (mesh._s > 1.5 && mesh._s <= 2) {
          // mesh._s=1.5，透明度=1 mesh._s=2，透明度=0
          mesh.material.opacity = 1 - (mesh._s - 1.5) * 2
        } else {
          mesh._s = 1.0
        }
      })
    }
    this.renderer.render(this.scene, this.camera)
    this.labelRenderer.render(this.scene, this.camera)
  }

  /**销毁*/
  destroy() {
    this.animation && cancelAnimationFrame(this.animation)
    try {
      this.scene.clear()
      this.renderer.dispose()
      this.renderer.forceContextLoss()
      this.renderer.content = null
      const gl = this.renderer.domElement.getContext('webgl')
      gl && gl.getExtension('WEBGL_lose_context').loseContext()
    } catch (e) {
      console.log(e)
    }
  }

}

export default threeUtils;
